<?php

/**
 * Created by PhpStorm.
 * User: lili
 * Date: 19-1-20
 * Time: 下午4:40
 */


require "vendor/autoload.php";
require "pdo.php";

function msectime() {
    list($msec, $sec) = explode(' ', microtime());
    $msectime = (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
    return $msectime;
}




class RedisLock
{
    public $objRedis = null;
    public $timeout = 2000;
    /**
     * @desc 设置redis实例
     *
     * @param obj object | redis实例
     */
    public function __construct($obj)
    {
        $this->objRedis = $obj;
    }

    /**
     * @desc 获取锁键名
     */
    public function getLockCacheKey($key)
    {
        return "lock_{$key}";
    }

    /**
     * @desc 获取锁
     *
     * @param key string | 要上锁的键名
     * @param timeout int | 上锁时间
     */
    public function getLock($key, $timeout = NULL)
    {
        $timeout = $timeout ? $timeout : $this->timeout;
        $lockCacheKey = $this->getLockCacheKey($key);
        $expireAt = msectime() + $timeout;

        $isGet = (bool)$this->objRedis->setnx($lockCacheKey, $expireAt);
        if ($isGet) {
            return $expireAt;
        }

        while (1) {
            usleep(10);
            $time = msectime();

            $oldExpire = $this->objRedis->get($lockCacheKey);
//            echo $time.'  ';
            if ($oldExpire >= $time) {
                continue;
            }
            $newExpire = $time + $timeout;
            $expireAt = $this->objRedis->getset($lockCacheKey, $newExpire);
            if ($oldExpire != $expireAt) {
                continue;
            }
            $isGet = $newExpire;
            break;
        }
        return $isGet;
    }

    /**
     * @desc 释放锁
     *
     * @param key string | 加锁的字段
     * @param newExpire int | 加锁的截止时间
     *
     * @return bool | 是否释放成功
     */
    public function releaseLock($key, $newExpire)
    {
        $lockCacheKey = $this->getLockCacheKey($key);
        if ($newExpire >= msectime()) {
            return $this->objRedis->del($lockCacheKey);
        }
        return true;
    }
}




/*
 *

$client = new Predis\Client([
    'scheme' => 'tcp',
    'host'   => '127.0.0.1',
    'port'   => 6379,
]);


$start_time = microtime(true);
$lock = new RedisLock($client);
$key = "name";
$client->set($key, 1);
for ($i = 0; $i < 100; $i++) {
    $newExpire = $lock->getLock($key);
    $num = $client->get($key);
    $num++;
    $client->set($key, $num);
    $lock->releaseLock($key, $newExpire);
}
$end_time = microtime(true);

echo "花费时间 ： ". ($end_time - $start_time) . "\n";

*/


$client = new Predis\Client([
    'scheme' => 'tcp',
    'host'   => '127.0.0.1',
    'port'   => 6379,
]);

$lock = new RedisLock($client);
$key = "name";
$client->setnx($key, 0);
$newExpire = $lock->getLock($key);
$num = $client->get($key);
$num++;
$client->set($key, $num);



//执行代码
pdoms($num);
//end









$lock->releaseLock($key, $newExpire);

